package com.uyayo.system.config.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.uyayo.framework.common.exception.CodeMultipleException;
import com.uyayo.framework.common.exception.ParentNotFoundException;
import com.uyayo.framework.pagehelper.pojo.OrderBy;
import com.uyayo.framework.pagehelper.pojo.PageBean;
import com.uyayo.framework.pagehelper.util.OrderByUtil;
import com.uyayo.system.authority.entity.SysResource;
import com.uyayo.system.authority.entity.SysRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import com.uyayo.system.config.entity.SysDictionary;
import com.uyayo.system.config.entity.SysDictionaryData;
import com.uyayo.system.config.mapper.SysDictionaryDataMapper;
import com.uyayo.system.config.mapper.SysDictionaryMapper;
import com.uyayo.system.config.service.SysDictionaryService;

import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;



@Component
@Service("sysDictionaryService")
public class SysDictionaryServiceImpl implements SysDictionaryService {
	
	private final SysDictionaryMapper sysDictionaryMapper;
	
	
	private final SysDictionaryDataMapper sysDictionaryDataMapper;

	@Autowired
	public SysDictionaryServiceImpl(SysDictionaryMapper sysDictionaryMapper, SysDictionaryDataMapper sysDictionaryDataMapper) {
		this.sysDictionaryMapper = sysDictionaryMapper;
		this.sysDictionaryDataMapper = sysDictionaryDataMapper;
	}

	/**
	 * 为列表添加了缓存，查询一次过后，只要不重启服务，缓存一直存在，不需要再查询数据库了，节省了一些资源
	 * 
	 * 在ehcache.xml里面需要有对应的value
	 * 
	 * <cache name="DictionaryServiceCache"
	 * 
	 * key是自己设定的一个ID，用来标识缓存
	 */
	@Override
	//@Cacheable(value = "DictionaryServiceCache", key = "'DictionaryList'")
	public List<SysDictionary> selectSysDictionary(SysDictionary dictionary) {
		List<SysDictionary> dictionaries;
		dictionaries = sysDictionaryMapper.select(dictionary);
		dictionaries = new ArrayList<>(new HashSet<>(dictionaries));// 去重
		// 排序
		Collections.sort(dictionaries, (o1, o2) -> {
            if (o1.getSeq() == null) {
                o1.setSeq(1000);
            }
            if (o2.getSeq() == null) {
                o2.setSeq(1000);
            }
            return o1.getSeq().compareTo(o2.getSeq());
        });
		return dictionaries;
	}

	@Override
	public SysDictionary getDictionaryById(Long id){
		return sysDictionaryMapper.selectByPrimaryKey(id);
	}

	@Override
	public SysDictionary getDictionaryByCode(String code) {
		SysDictionary sysDictionary = new SysDictionary();
		sysDictionary.setCode(code);
		sysDictionary = sysDictionaryMapper.selectOne(sysDictionary);
		return sysDictionary;
	}

	@Override
	public int insertDictionary(SysDictionary sysDictionary) {
		return sysDictionaryMapper.insertSelective(sysDictionary);
	}

	@Override
	public int updateDictionary(SysDictionary sysDictionary) {
		return sysDictionaryMapper.updateByPrimaryKeySelective(sysDictionary);
	}
	
	
	@Override
	public List<SysDictionaryData> selectSysDictionaryData(
			SysDictionaryData dictionaryData) {
		if(dictionaryData !=null){
			Example example = new Example(SysDictionaryData.class);  
			Criteria criteria = example.createCriteria();
			criteria.andEqualTo(dictionaryData);
			List<SysDictionaryData> dictionarieDatas = sysDictionaryDataMapper.selectByExample(example);
			return dictionarieDatas;
		}
		return new ArrayList<>();
	}
	

	@Override
	public int deleteDictionary(Long id) {
		int countDelete = sysDictionaryMapper.deleteByPrimaryKey(id);
		return countDelete;
	}
	
	@Override
	public int deleteDictionaryData(Long id) {
		int countDelete = sysDictionaryDataMapper.deleteByPrimaryKey(id);
		return countDelete;
	}

	@Override
	public PageBean<SysDictionary> selectSysDictionaryByPage(int pageCurrent, Integer pageSize, String sort, String order, SysDictionary sysDictionary) {
		List<SysDictionary> params;
		//分页处理
		List<OrderBy> orderBies = new ArrayList<>();
		orderBies.add(new OrderBy("type", "type"));
		orderBies.add(new OrderBy("code", "code"));
		orderBies.add(new OrderBy("name", "name"));
		orderBies.add(new OrderBy("value", "value"));
		orderBies.add(new OrderBy("description", "description"));
		orderBies.add(new OrderBy("createdTime", "created_time"));
		orderBies.add(new OrderBy("modifiedTime", "modified_time"));
		orderBies.add(new OrderBy("remark", "remark"));
		OrderByUtil orderByUtil = new OrderByUtil();
		String orderBy = orderByUtil.getOrderBy(orderBies, sort, order);
		PageHelper.startPage(pageCurrent, pageSize);
		Example example = new Example(SysRole.class);
		if(!StringUtils.isEmpty(orderBy)){
			example.setOrderByClause(orderBy);
		}
		Criteria criteria = example.createCriteria();
		if(!StringUtils.isEmpty(sysDictionary.getName())){
			criteria.andLike("name","%"+sysDictionary.getName()+"%");
		}
		params = sysDictionaryMapper.selectByExample(example);

		//取记录总条数
		PageInfo<SysDictionary> pageInfo = new PageInfo<>(params);

		return new PageBean<>(pageInfo.getTotal(), pageCurrent, pageSize, params);
	}


	@Override
	public List<SysDictionaryData> selectSysDictinaryDataByCode(String code){
		SysDictionary dictionary = new SysDictionary();
		dictionary.setCode(code);
		SysDictionary sd = sysDictionaryMapper.selectOne(dictionary);
		if(sd !=null){
			Example example = new Example(SysDictionaryData.class);  
			Criteria criteria = example.createCriteria();
			criteria.andEqualTo("dictionaryId", sd.getId());
			return sysDictionaryDataMapper.selectByExample(example);
		}
		return new ArrayList<>();
	}


	@Override
	public SysDictionaryData getDictionaryDataByCode(String code) {
		SysDictionaryData sysDictionaryData = new SysDictionaryData();
		sysDictionaryData.setCode(code);
		sysDictionaryData = sysDictionaryDataMapper.selectOne(sysDictionaryData);
		return sysDictionaryData;
	}

	@Override
	public SysDictionaryData selectDictionaryDataById(Long id) {
		SysDictionaryData sysDictionaryData = new SysDictionaryData();
		try {
			sysDictionaryData = sysDictionaryDataMapper.selectByPrimaryKey(id);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sysDictionaryData;
	}


	@Override
	public int insertDictionaryData(SysDictionaryData sysDictionaryData) throws ParentNotFoundException, CodeMultipleException {
		Long parentId = sysDictionaryData.getParentId();
		SysDictionaryData sysDictionaryDataCondition = new SysDictionaryData();
		sysDictionaryDataCondition.setCode(sysDictionaryData.getCode());
		SysDictionaryData sysDictionaryDataTest = sysDictionaryDataMapper.selectOne(sysDictionaryDataCondition);
		if(sysDictionaryDataTest!=null){
			throw new CodeMultipleException("Code multiple error!");
		}

		if(!StringUtils.isEmpty(parentId)){
			SysDictionaryData sysDictionaryDataParent = selectDictionaryDataById(parentId);
			if(sysDictionaryDataParent==null){
				throw new ParentNotFoundException("Parent not found!");
			}
		}

		SysDictionary sysDictionary = new SysDictionary();
		sysDictionary.setId(sysDictionaryData.getDictionaryId());
		sysDictionary = sysDictionaryMapper.selectOne(sysDictionary);
		if(sysDictionary==null){
			return 0;
		}
		int count = sysDictionaryDataMapper.insertSelective(sysDictionaryData);
		if(count >0){
			updateHasChildrennToParent( parentId);
		}
		return count;
	}

	/**
	 * 迭代检查选择的上级id是否是自己的子级
	 * @param parentIdOld 原上级id
	 * @param parentIdNew	新上级id
	 * @param sysDictionaryDataChild 子机构
	 * @param sysDictionaryDataParent 父机构
	 */
	private void recursiveCheckParentIsChildren(Long parentIdOld, Long parentIdNew, SysDictionaryData sysDictionaryDataChild, SysDictionaryData sysDictionaryDataParent){
		if (selectCountByParentId(sysDictionaryDataChild.getId()) > 0) {
			Example example = new Example(SysResource.class);
			Example.Criteria criteria = example.createCriteria();
			criteria.andEqualTo("parentId",sysDictionaryDataChild.getId());
			List<SysDictionaryData> sysDictionaryDatas = sysDictionaryDataMapper.selectByExample(example);
			if (!sysDictionaryDatas.isEmpty()) {
				for(SysDictionaryData sysDictionaryData:sysDictionaryDatas){
					if(sysDictionaryData.getId()==parentIdNew){
						sysDictionaryDataParent.setParentId(parentIdOld);
						sysDictionaryDataMapper.updateByPrimaryKeySelective(sysDictionaryDataParent);
					}else {
						recursiveCheckParentIsChildren(parentIdOld, parentIdNew, sysDictionaryData, sysDictionaryDataParent);
					}
				}
			}
		}
	}
	@Override
	public int updateDictionaryData(SysDictionaryData sysDictionaryData) throws CodeMultipleException, ParentNotFoundException {
		SysDictionaryData sysDictionaryDataCondition = new SysDictionaryData();
		sysDictionaryDataCondition.setCode(sysDictionaryData.getCode());
		SysDictionaryData sysDictionaryDataTest = sysDictionaryDataMapper.selectOne(sysDictionaryDataCondition);
		if(sysDictionaryDataTest!=null && sysDictionaryData.getId()!=sysDictionaryDataTest.getId()){
			throw new CodeMultipleException("Code multiple error!");
		}

		SysDictionaryData sysDictionaryDataOld = selectDictionaryDataById(sysDictionaryData.getId());

			if(sysDictionaryData.getParentId()==null){
				sysDictionaryData.setParentId(0L);
			}
			Long parentId = sysDictionaryData.getParentId();
			if(parentId!=0){

			//获取修改的父级资源
			SysDictionaryData sysDictionaryDataParent = selectDictionaryDataById(parentId);
			if(sysDictionaryDataParent==null){
				throw new ParentNotFoundException("Parent not found!");
			}
			if (selectCountByParentId(sysDictionaryDataOld.getId()) > 0) {
				Example example = new Example(SysDictionaryData.class);
				Example.Criteria criteria = example.createCriteria();
				criteria.andEqualTo("parentId",sysDictionaryDataOld.getId());
				List<SysDictionaryData> sysDictionaryDatas = sysDictionaryDataMapper.selectByExample(example);
				if (!sysDictionaryDatas.isEmpty()) {
					for(SysDictionaryData sysDictionaryData_:sysDictionaryDatas){
						if(sysDictionaryData_.getId()==parentId){
							sysDictionaryDataParent.setParentId(sysDictionaryDataOld.getParentId());
							sysDictionaryDataMapper.updateByPrimaryKeySelective(sysDictionaryDataParent);
						}else{
							recursiveCheckParentIsChildren(sysDictionaryDataOld.getParentId(),sysDictionaryData.getParentId(),sysDictionaryData,sysDictionaryDataParent);
						}
					}
				}
			}
		}
		if(selectCountByParentId(sysDictionaryData.getId())>0) {
			sysDictionaryData.setHasChildren(true);
		}else{
			sysDictionaryData.setHasChildren(false);
		}
		int count = sysDictionaryDataMapper.updateByPrimaryKeySelective(sysDictionaryData);
		if(count<=0){
			return count;
		}
		updateHasChildrennToParent(parentId);
		if(sysDictionaryDataOld!=null){
			updateHasChildrennToParent(sysDictionaryDataOld.getParentId());
		}
		return count;

	}

	@Override
	public int selectCountByParentId(Long parentId) {
		SysDictionaryData sysDictionaryData = new SysDictionaryData();
		sysDictionaryData.setParentId(parentId);
		return sysDictionaryDataMapper.selectCount(sysDictionaryData);
	}

	/**
	 * 修改父级是否含子级
	 * @param parentId 父资源id
	 */
	private void  updateHasChildrennToParent(Long parentId){
		if(!StringUtils.isEmpty(parentId)){
			SysDictionaryData sysDictionaryData = new SysDictionaryData();
			sysDictionaryData.setId(parentId);
			if(selectCountByParentId(parentId)>0) {
				sysDictionaryData.setHasChildren(true);
			}else{
				sysDictionaryData.setHasChildren(false);
			}
			sysDictionaryDataMapper.updateByPrimaryKeySelective(sysDictionaryData);
		}
	}
}
